/* 
 *  This is factory method sample
 *  notes by heefan
 */

#include <iostream> #include <cstring> 
using namespace std;

/*
 *  Product Base [Abstract class] 
 */
class Document
{
public:
	Document (char* fn)
	{
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
		strcpy (m_name, fn);
	}
	virtual void open() = 0;  // for subclass override
	virtual void close() = 0; // for subclass override
	char* getName()  //share m_name to all subclass
	{
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
		return m_name;
	}
private:
	char m_name[20];
};

/*
 * Concrete Product :Override and implement its own features
 */
class MyDocument : public Document
{
public:
	MyDocument (char* fn) : Document (fn) {};
	void open() {
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
	}
	void close() {
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
	}
};

/*
 *  Creator Base:  factory method (pure virtual function)
 *  
 */
class Application 
{
public:
	Application() : m_index(0) {
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
	}
	
	// the client will call this "entry point" of the framework
	void newDocument (char* name) {
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
		m_docs[m_index] = createDocument(name);
		m_docs[m_index++]->open();
	}
	void openDocument() {
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
	}
	void reportDocs() {
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
		for (int i = 0 ; i < m_index ; i++) {
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
			cout << "   " << m_docs[i]->getName() << endl;
		}
	}

	virtual Document* createDocument (char* ) = 0; //factory method
private:
	int m_index;
	Document* m_docs[10];
};

/* 
 * Concrete Creator 
 * Implement/Override its own feature and factory method
 */
class MyApplication : public Application {
public:
	MyApplication ()
	{
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
	}

	//Implement Factory method
	Document* createDocument(char* fn) {
		cout << __FILE__ << ":" << __func__ <<":" << __LINE__ << endl;
		return new MyDocument(fn);
	}
};

/* ************** Main ********************* */
int main()
{
	MyApplication myApp;
	
	myApp.newDocument((char*)"foo"); /* Client require open a document called foo */
	myApp.newDocument((char*)"bar");
	myApp.reportDocs();
	return 0;
}


/*
 *  Result:
 *  main.cpp:Application:51
 *  main.cpp:MyApplication:84
 *  main.cppMyApplication85
 *  main.cpp:newDocument:56 
 *  main.cpp:createDocument:90
 *  main.cpp:Document:17
 *  main.cpp:open:38
 *  main.cpp:newDocument:56
 *  main.cpp:createDocument:90
 *  main.cpp:Document:17
 *  main.cpp:open:38
 *  main.cpp:reportDocs:64
 *  main.cpp:reportDocs:66
 *  main.cpp:getName:24
 *  foo
 *  main.cpp:reportDocs:66
 *  main.cpp:getName:24
 *  bar
 *
 */
